﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;
using System.Web;

namespace RastinArgham.CRM.Business
{
    public class ImageExport
    {
        public static string ExportRange(DateTime StartDate, DateTime EndDate, String Path) {

            CRMRepository repo = new CRMRepository();
            List<Contact> contacts = repo.GetServiceOrdersByDate(StartDate, EndDate).Select( o => o.Contact ).ToList();
  
            string folderPath = Path + Guid.NewGuid().ToString();
            Directory.CreateDirectory(HttpContext.Current.Server.MapPath(folderPath));

            foreach (var c in contacts) {
                Export(c.ContactId, folderPath + "/", false, true);
            }

            ZipFolder(HttpContext.Current.Server.MapPath(folderPath));

            return folderPath + ".zip";
        }

        public static string Export(int contactId, string PATHToSave, bool zip, bool createFolder)
        {
            CRMRepository repo = new CRMRepository();
            Contact c = repo.GetContactById(contactId);

            string folderPath = PATHToSave;

            if (c == null)
                return String.Empty;

            string folderName = String.Empty;

            if (createFolder)
            {
                Order order = c.Orders.Where(o => o.SubID != null).FirstOrDefault();
                if (order != null && !String.IsNullOrEmpty(order.SubID))
                    folderName = order.SubID.Trim();
                else
                    folderName = c.ContactId.ToString();

                folderPath += folderName;

                try
                {
                    Directory.CreateDirectory(HttpContext.Current.Server.MapPath(folderPath));
                }
                catch (Exception ex)
                {
                    throw new Exception("Create Directory Failed for contact id + " + contactId.ToString() + " with path: " + folderPath + " - With Exception: " + ex.ToString());
                }
            }
            
            string filePath = HttpContext.Current.Server.MapPath(folderPath);
            bool hasAnyPhoto = false;


            if (c.ContactTypeId == (int)ContactTypes.Personal)
            {
                PersonalContact pc = c.PersonalContacts.FirstOrDefault();

                if (pc.ServicePhoto != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs1 = new FileStream(filePath + "\\" + folderName + "L.jpg", FileMode.Create);
                    fs1.Write(pc.ServicePhoto, 0, pc.ServicePhoto.Length);

                    fs1.Flush();
                    fs1.Close();
                    fs1.Dispose();
                }

                if (pc.IdentityPhoto != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs2 = new FileStream(filePath + "\\" + folderName + "K.jpg", FileMode.Create);
                    fs2.Write(pc.IdentityPhoto, 0, pc.IdentityPhoto.Length);
                    fs2.Flush();
                    fs2.Close();
                    fs2.Dispose();
                }
            }

            if (c.ContactTypeId == (int)ContactTypes.Company)
            {
                CompanyContact cc = c.CompanyContacts.FirstOrDefault();

                if (cc.ServicePhoto != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs1 = new FileStream(filePath + "\\" + folderName + "L.jpg", FileMode.Create);
                    fs1.Write(cc.ServicePhoto, 0, cc.ServicePhoto.Length);
                    fs1.Flush();
                    fs1.Close();
                    fs1.Dispose();
                }

                if (cc.ChargePhoto != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs2 = new FileStream(filePath + "\\" + folderName + "CP.jpg", FileMode.Create);
                    fs2.Write(cc.ChargePhoto, 0, cc.ChargePhoto.Length);
                    fs2.Flush();
                    fs2.Close();
                    fs2.Dispose();
                }


                if (cc.IdPhoto != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs3 = new FileStream(filePath + "\\" + folderName + "K.jpg", FileMode.Create);
                    fs3.Write(cc.IdPhoto, 0, cc.IdPhoto.Length);
                    fs3.Flush();
                    fs3.Close();
                    fs3.Dispose();
                }
            }

            for (int i = 0; i < c.ServiceOrders.Count; i++)
            {
                if (c.ServiceOrders[i].InstallationForm != null)
                {
                    hasAnyPhoto = true;
                    FileStream fs3 = new FileStream(filePath + "\\" + folderName + "TR" + i.ToString() + ".jpg", FileMode.Create);
                    fs3.Write(c.ServiceOrders[i].InstallationForm, 0, c.ServiceOrders[i].InstallationForm.Length);
                    fs3.Flush();
                    fs3.Close();
                    fs3.Dispose();
                }
            }

            if (!hasAnyPhoto)
            {
                Directory.Delete(filePath, true);
                return String.Empty;
            }

            if (zip)
            {
                ZipFolder(HttpContext.Current.Server.MapPath(folderPath));
                return folderPath + ".zip";
            }
            else
            {
                return folderPath;
            }
        }

        public static void ZipFolder(string folderPath)
        {
            // Depending on the directory this could be very large and would require more attention
            // in a commercial package.
            string[] filenames = Directory.GetFiles(folderPath);

            // 'using' statements guarantee the stream is closed properly which is a big source
            // of problems otherwise.  Its exception safe as well which is great.
            using (ZipOutputStream s = new ZipOutputStream(File.Create(folderPath + ".zip")))
            {

                s.SetLevel(9); // 0 - store only to 9 - means best compression

                byte[] buffer = new byte[4096];

                foreach (string file in filenames)
                {

                    // Using GetFileName makes the result compatible with XP
                    // as the resulting path is not absolute.
                    ZipEntry entry = new ZipEntry(Path.GetFileName(file));

                    // Setup the entry data as required.

                    // Crc and size are handled by the library for seakable streams
                    // so no need to do them here.

                    // Could also use the last write time or similar for the file.
                    entry.DateTime = DateTime.Now;
                    s.PutNextEntry(entry);

                    using (FileStream fs = File.OpenRead(file))
                    {

                        // Using a fixed size buffer here makes no noticeable difference for output
                        // but keeps a lid on memory usage.
                        int sourceBytes;
                        do
                        {
                            sourceBytes = fs.Read(buffer, 0, buffer.Length);
                            s.Write(buffer, 0, sourceBytes);
                        } while (sourceBytes > 0);
                    }
                }

                // Finish/Close arent needed strictly as the using statement does this automatically

                // Finish is important to ensure trailing information for a Zip file is appended.  Without this
                // the created file would be invalid.
                s.Finish();

                // Close is important to wrap things up and unlock the file.
                s.Close();
            }
        }
    }
}
